// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

<template>
  <a-spin :spinning="fetchLoading">
    <a-button
      type="dashed"
      style="width: 100%;margin-bottom: 20px;"
      :disabled="!('createNetwork' in $store.getters.apis)"
      @click="handleOpenModal">
      <template #icon><plus-outlined /></template>
      {{ $t('label.add.new.tier') }}
    </a-button>
    <a-list class="list">
      <a-list-item v-for="(network, idx) in networks" :key="idx" class="list__item">
        <div class="list__item-outer-container">
          <div class="list__item-container">
            <div class="list__col">
              <div class="list__label">
                {{ $t('label.name') }}
              </div>
              <div>
                <router-link :to="{ path: '/guestnetwork/' + network.id }">{{ network.name }} </router-link>
                <a-tag v-if="network.broadcasturi">{{ network.broadcasturi }}</a-tag>
              </div>
            </div>
            <div class="list__col">
              <div class="list__label">{{ $t('label.state') }}</div>
              <div><status :text="network.state" displayText></status></div>
            </div>
            <div class="list__col">
              <div class="list__label">
                {{ $t('label.cidr') }}
              </div>
              <div>{{ network.cidr }}</div>
            </div>
            <div class="list__col">
              <div class="list__label">
                {{ $t('label.aclid') }}
              </div>
              <div>
                <router-link :to="{ path: '/acllist/' + network.aclid }">
                  {{ network.aclname }}
                </router-link>
              </div>
            </div>
          </div>
          <a-collapse :bordered="false" style="margin-left: -18px">
            <template #expandIcon="props">
              <caret-right-outlined :rotate="props.isActive ? 90 : 0" />
            </template>
            <a-collapse-panel :header="$t('label.instances')" key="vm" :style="customStyle">
              <a-button
                type="dashed"
                style="margin-bottom: 15px; width: 100%"
                :disabled="!('deployVirtualMachine' in $store.getters.apis)"
                @click="$router.push({ path: '/action/deployVirtualMachine', query: { networkid: network.id, zoneid: network.zoneid } })">
                <template #icon><plus-outlined /></template>
                {{ $t('label.vm.add') }}
              </a-button>
              <a-table
                class="table"
                size="small"
                :columns="vmCols"
                :dataSource="vms[network.id]"
                :rowKey="item => item.id"
                :pagination="false"
                :loading="fetchLoading">
                <template #bodyCell="{ column, record }">
                  <template v-if="column.key === 'name'">
                    <router-link :to="{ path: '/vm/' + record.id}">{{ record.name }}
                    </router-link>
                  </template>
                  <template v-if="column.key === 'state'">
                    <status :text="record.state" displayText></status>
                  </template>
                  <template v-if="column.key === 'ip'">
                    <div v-for="nic in record.nic" :key="nic.id">
                      {{ nic.networkid === network.id ? nic.ipaddress : '' }}
                    </div>
                  </template>
                </template>
              </a-table>
              <a-divider/>
              <a-pagination
                class="row-element pagination"
                size="small"
                :current="page"
                :pageSize="pageSize"
                :total="itemCounts.vms[network.id]"
                :showTotal="total => `${$t('label.total')} ${total} ${$t('label.items')}`"
                :pageSizeOptions="['10', '20', '40', '80', '100']"
                @change="changePage"
                @showSizeChange="changePageSize"
                showSizeChanger>
                <template #buildOptionText="props">
                  <span>{{ props.value }} / {{ $t('label.page') }}</span>
                </template>
              </a-pagination>
            </a-collapse-panel>
            <a-collapse-panel :header="$t('label.internal.lb')" key="ilb" :style="customStyle" :collapsible="displayCollapsible[network.id] ? null: 'disabled'" >
              <a-button
                type="dashed"
                style="margin-bottom: 15px; width: 100%"
                :disabled="!('createLoadBalancer' in $store.getters.apis)"
                @click="handleAddInternalLB(network.id)">
                <template #icon><plus-outlined /></template>
                {{ $t('label.add.internal.lb') }}
              </a-button>
              <a-table
                class="table"
                size="small"
                :columns="internalLbCols"
                :dataSource="internalLB[network.id]"
                :rowKey="item => item.id"
                :pagination="false"
                :loading="fetchLoading">
                <template #bodyCell="{ column, record }">
                  <template v-if="column.key === 'name'">
                    <router-link :to="{ path: '/ilb/'+ record.id}">{{ record.name }}
                    </router-link>
                  </template>
                </template>
              </a-table>
              <a-divider/>
              <a-pagination
                class="row-element pagination"
                size="small"
                :current="page"
                :pageSize="pageSize"
                :total="itemCounts.internalLB[network.id]"
                :showTotal="total => `${$t('label.total')} ${total} ${$t('label.items')}`"
                :pageSizeOptions="['10', '20', '40', '80', '100']"
                @change="changePage"
                @showSizeChange="changePageSize"
                showSizeChanger>
                <template #buildOptionText="props">
                  <span>{{ props.value }} / {{ $t('label.page') }}</span>
                </template>
              </a-pagination>
            </a-collapse-panel>
          </a-collapse>
        </div>
      </a-list-item>
    </a-list>

    <a-modal
      :visible="showCreateNetworkModal"
      :title="$t('label.add.new.tier')"
      :maskClosable="false"
      :closable="true"
      :footer="null"
      @cancel="showCreateNetworkModal = false">
      <a-spin :spinning="modalLoading" v-ctrl-enter="handleAddNetworkSubmit">
        <a-form
          layout="vertical"
          :ref="formRef"
          :model="form"
          :rules="rules"
          @finish="handleAddNetworkSubmit"
         >
          <a-form-item ref="name" name="name" :colon="false">
            <template #label>
              <tooltip-label :title="$t('label.name')" :tooltip="$t('label.create.tier.name.description')"/>
            </template>
            <a-input
              :placeholder="$t('label.create.tier.name.description')"
              v-model:value="form.name"
              v-focus="true"></a-input>
          </a-form-item>
          <a-form-item ref="networkOffering" name="networkOffering" :colon="false">
            <template #label>
              <tooltip-label :title="$t('label.networkofferingid')" :tooltip="$t('label.create.tier.networkofferingid.description')"/>
            </template>
            <a-select
              v-model:value="form.networkOffering"
              @change="val => { this.handleNetworkOfferingChange(val) }"
              showSearch
              optionFilterProp="label"
              :filterOption="(input, option) => {
                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
              }" >
              <a-select-option v-for="item in networkOfferings" :key="item.id" :value="item.id" :label="item.displaytext || item.name || item.description">
                {{ item.displaytext || item.name || item.description }}
              </a-select-option>
            </a-select>
          </a-form-item>
          <a-form-item
            v-if="setMTU"
            ref="privatemtu"
            name="privatemtu">
            <template #label>
              <tooltip-label :title="$t('label.privatemtu')" :tooltip="$t('label.privatemtu')"/>
            </template>
            <a-input-number
              style="width: 100%;"
              v-model:value="form.privatemtu"
              :placeholder="$t('label.privatemtu')"
              @change="updateMtu()"/>
              <div style="color: red" v-if="errorPrivateMtu" v-html="errorPrivateMtu.replace('%x', privateMtuMax)"></div>
          </a-form-item>
          <a-form-item ref="vlan" name="vlan" v-if="!isObjectEmpty(selectedNetworkOffering) && selectedNetworkOffering.specifyvlan">
            <template #label>
              <tooltip-label :title="$t('label.vlan')" :tooltip="$t('label.vlan')"/>
            </template>
            <a-input
              v-model:value="form.vlan"
              :placeholder="$t('label.vlan')"/>
          </a-form-item>
          <a-form-item ref="asnumber" name="asnumber" v-if="!isObjectEmpty(selectedNetworkOffering) && selectedNetworkOffering.specifyasnumber">
            <template #label>
              <tooltip-label :title="$t('label.asnumber')" :tooltip="$t('label.asnumber')"/>
            </template>
            <a-select
             v-model:value="form.asnumber"
              showSearch
              optionFilterProp="label"
              :filterOption="(input, option) => {
                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
              }"
              :loading="asNumberLoading"
              :placeholder="$t('label.asnumber')"
              @change="val => { handleASNumberChange(val) }">
              <a-select-option v-for="(opt, optIndex) in asNumbersZone" :key="optIndex" :label="opt.asnumber">
                {{ opt.asnumber }}
              </a-select-option>
            </a-select>
          </a-form-item>
          <a-form-item ref="gateway" name="gateway" :colon="false">
            <template #label>
              <tooltip-label :title="$t('label.gateway')" :tooltip="gatewayPlaceholder"/>
            </template>
            <a-input
              :placeholder="gatewayPlaceholder"
              v-model:value="form.gateway"></a-input>
          </a-form-item>
          <a-form-item ref="netmask" name="netmask" :colon="false">
            <template #label>
              <tooltip-label :title="$t('label.netmask')" :tooltip="netmaskPlaceholder"/>
            </template>
            <a-input
              :placeholder="netmaskPlaceholder"
              v-model:value="form.netmask"></a-input>
          </a-form-item>
          <a-form-item ref="externalId" name="externalId" :colon="false">
            <template #label>
              <tooltip-label :title="$t('label.externalid')" :tooltip="$t('label.create.tier.externalid.description')"/>
            </template>
            <a-input
              :placeholder=" $t('label.create.tier.externalid.description')"
              v-model:value="form.externalId"/>
          </a-form-item>
          <a-form-item ref="acl" name="acl" :colon="false">
            <template #label>
              <tooltip-label :title="$t('label.aclid')" :tooltip="$t('label.create.tier.aclid.description')"/>
            </template>
            <a-select
              :placeholder="$t('label.create.tier.aclid.description')"
              v-model:value="form.acl"
              @change="val => { handleNetworkAclChange(val) }"
              showSearch
              optionFilterProp="label"
              :filterOption="(input, option) => {
                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
              }" >
              <a-select-option v-for="item in networkAclList" :key="item.id" :value="item.id" :label="`${item.name}(${item.description})`">
                <strong>{{ item.name }}</strong> ({{ item.description }})
              </a-select-option>
            </a-select>
          </a-form-item>
          <a-alert v-if="selectedNetworkAcl.name==='default_allow'" type="warning" show-icon>
            <template #message><div v-html="$t('message.network.acl.default.allow')"/></template>
          </a-alert>
          <a-alert v-else-if="selectedNetworkAcl.name==='default_deny'" type="warning" show-icon>
            <template #message><div v-html="$t('message.network.acl.default.deny')"/></template>
          </a-alert>
          <div :span="24" class="action-button">
            <a-button @click="showCreateNetworkModal = false">{{ $t('label.cancel') }}</a-button>
            <a-button type="primary" ref="submit" @click="handleAddNetworkSubmit">{{ $t('label.ok') }}</a-button>
          </div>
        </a-form>
      </a-spin>
    </a-modal>

    <a-modal
      :visible="showAddInternalLB"
      :title="$t('label.add.internal.lb')"
      :maskClosable="false"
      :closable="true"
      :footer="null"
      @cancel="showAddInternalLB = false">
      <a-spin :spinning="modalLoading" v-ctrl-enter="handleAddInternalLBSubmit">
        <a-form
          layout="vertical"
          :ref="formRef"
          :model="form"
          :rules="rules"
          @finish="handleAddInternalLBSubmit"
         >
          <a-form-item ref="name" name="name" :label="$t('label.name')">
            <a-input
              v-focus="true"
              :placeholder="$t('label.internallb.name.description')"
              v-model:value="form.name"/>
          </a-form-item>
          <a-form-item ref="description" name="description" :label="$t('label.description')">
            <a-input
              :placeholder="$t('label.internallb.description')"
              v-model:value="form.description"/>
          </a-form-item>
          <a-form-item ref="sourceIP" name="sourceIP" :label="$t('label.sourceipaddress')">
            <a-input
              :placeholder="$t('label.internallb.sourceip.description')"
              v-model:value="form.sourceIP"/>
          </a-form-item>
          <a-form-item ref="sourcePort" name="sourcePort" :label="$t('label.sourceport')">
            <a-input v-model:value="form.sourcePort"/>
          </a-form-item>
          <a-form-item ref="instancePort" name="instancePort" :label="$t('label.instanceport')">
            <a-input v-model:value="form.instancePort"/>
          </a-form-item>
          <a-form-item ref="algorithm" name="algorithm" :label="$t('label.algorithm')">
            <a-select
              v-model:value="form.algorithm"
              showSearch
              optionFilterProp="label"
              :filterOption="(input, option) => {
                return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
              }" >
              <a-select-option v-for="(key, idx) in Object.keys(algorithms)" :key="idx" :value="algorithms[key]" :label="key">
                {{ key }}
              </a-select-option>
            </a-select>
          </a-form-item>

          <div :span="24" class="action-button">
            <a-button @click="showAddInternalLB = false">{{ $t('label.cancel') }}</a-button>
            <a-button type="primary" ref="submit" @click="handleAddInternalLBSubmit">{{ $t('label.ok') }}</a-button>
          </div>
        </a-form>
      </a-spin>
    </a-modal>
  </a-spin>
</template>

<script>
import { ref, reactive, toRaw } from 'vue'
import { postAPI, getAPI } from '@/api'
import { mixinForm } from '@/utils/mixin'
import Status from '@/components/widgets/Status'
import TooltipLabel from '@/components/widgets/TooltipLabel'
import { getNetmaskFromCidr } from '@/utils/network'

export default {
  name: 'VpcTiersTab',
  mixins: [mixinForm],
  components: {
    Status,
    TooltipLabel
  },
  props: {
    resource: {
      type: Object,
      required: true
    },
    loading: {
      type: Boolean,
      default: false
    }
  },
  inject: ['parentFetchData'],
  data () {
    return {
      networks: [],
      networkid: '',
      fetchLoading: false,
      showCreateNetworkModal: false,
      showAddInternalLB: false,
      networkOfferings: [],
      networkAclList: [],
      selectedNetworkAcl: {},
      modalLoading: false,
      internalLB: {},
      LBPublicIPs: {},
      staticNats: {},
      vms: {},
      selectedNetworkOffering: {},
      privateMtuMax: 1500,
      errorPrivateMtu: '',
      gatewayPlaceholder: '',
      netmaskPlaceholder: '',
      algorithms: {
        Source: 'source',
        'Round-robin': 'roundrobin',
        'Least connections': 'leastconn'
      },
      internalLbCols: [
        {
          key: 'name',
          title: this.$t('label.name'),
          dataIndex: 'name'
        },
        {
          title: this.$t('label.sourceipaddress'),
          dataIndex: 'sourceipaddress'
        },
        {
          title: this.$t('label.algorithm'),
          dataIndex: 'algorithm'
        },
        {
          title: this.$t('label.account'),
          dataIndex: 'account'
        }
      ],
      vmCols: [
        {
          key: 'name',
          title: this.$t('label.name'),
          dataIndex: 'name'
        },
        {
          key: 'state',
          title: this.$t('label.state'),
          dataIndex: 'state'
        },
        {
          key: 'ip',
          title: this.$t('label.ip')
        }
      ],
      customStyle: 'margin-bottom: 0; border: none',
      page: 1,
      pageSize: 10,
      itemCounts: {
        internalLB: {},
        publicIps: {},
        snats: {},
        vms: {}
      },
      lbProviderMap: {
        publicLb: {
          vpc: ['Netscaler']
        }
      },
      publicLBExists: false,
      setMTU: false,
      isNsxEnabled: false,
      zoneExtNetProvider: null,
      isOfferingNatMode: false,
      isOfferingRoutedMode: false,
      displayCollapsible: [],
      selectedAsNumber: 0,
      asNumbersZone: []
    }
  },
  created () {
    this.initForm()
    this.fetchData()
  },
  watch: {
    loading (newData, oldData) {
      if (!newData && this.resource.id) {
        this.fetchData()
      }
    }
  },
  methods: {
    isASNumberRequired () {
      return !this.isObjectEmpty(this.selectedNetworkOffering) && this.selectedNetworkOffering.specifyasnumber && this.selectedNetworkOffering.routingmode && this.selectedNetworkOffering.routingmode.toLowerCase() === 'dynamic'
    },
    handleASNumberChange (selectedIndex) {
      this.selectedAsNumber = this.asNumbersZone[selectedIndex].asnumber
      this.form.asnumber = this.selectedAsNumber
    },
    fetchZoneASNumbers () {
      const params = {}
      this.asNumberLoading = true
      params.zoneid = this.resource.zoneid
      params.isallocated = false
      getAPI('listASNumbers', params).then(json => {
        this.asNumbersZone = json.listasnumbersresponse.asnumber
        this.asNumberLoading = false
      })
    },
    isObjectEmpty (obj) {
      return !(obj !== null && obj !== undefined && Object.keys(obj).length > 0 && obj.constructor === Object)
    },
    initForm () {
      this.formRef = ref()
      this.form = reactive({})
      this.rules = reactive({})
    },
    showIlb (network, networkOffering) {
      return ((networkOffering.supportsinternallb && network.service.filter(s => (s.name === 'Lb') && (s.capability.filter(c => c.name === 'LbSchemes' && c.value.split(',').includes('Internal')).length > 0)).length > 0)) || false
    },
    updateMtu () {
      if (this.form.privatemtu > this.privateMtuMax) {
        this.errorPrivateMtu = `${this.$t('message.error.mtu.private.max.exceed')}`
        this.form.privatemtu = this.privateMtuMax
      } else {
        this.errorPrivateMtu = ''
      }
    },
    fetchData () {
      this.networks = this.resource.network
      this.fetchMtuForZone()
      this.getVpcNetworkOffering()
      if (!this.networks || this.networks.length === 0) {
        return
      }
      for (const network of this.networks) {
        this.fetchLoadBalancers(network.id)
        this.fetchVMs(network.id)
        this.updateDisplayCollapsible(network.networkofferingid, network)
      }
      this.publicLBNetworkExists()
    },
    fetchMtuForZone () {
      getAPI('listZones', {
        id: this.resource.zoneid
      }).then(json => {
        this.setMTU = json?.listzonesresponse?.zone?.[0]?.allowuserspecifyvrmtu || false
        this.privateMtuMax = json?.listzonesresponse?.zone?.[0]?.routerprivateinterfacemaxmtu || 1500
        this.isNsxEnabled = json?.listzonesresponse?.zone?.[0]?.isnsxenabled || false
        this.zoneExtNetProvider = json?.listzonesresponse?.zone?.[0]?.provider || null
      })
    },
    fetchNetworkAclList () {
      this.fetchLoading = true
      this.modalLoading = true
      getAPI('listNetworkACLLists', { vpcid: this.resource.id }).then(json => {
        this.networkAclList = json.listnetworkacllistsresponse.networkacllist || []
        this.handleNetworkAclChange(null)
      }).catch(error => {
        this.$notifyError(error)
      }).finally(() => {
        this.fetchLoading = false
        this.modalLoading = false
      })
    },
    getNetworkOffering (networkId) {
      return new Promise((resolve, reject) => {
        getAPI('listNetworkOfferings', {
          id: networkId
        }).then(json => {
          var networkOffering = json.listnetworkofferingsresponse.networkoffering[0]
          resolve(networkOffering)
        }).catch(e => {
          reject(e)
        })
      })
    },
    updateDisplayCollapsible (offeringId, network) {
      getAPI('listNetworkOfferings', {
        id: offeringId
      }).then(json => {
        var networkOffering = json.listnetworkofferingsresponse.networkoffering[0]
        this.displayCollapsible[network.id] = this.showIlb(network, networkOffering)
      }).catch(e => {
        this.$notifyError(e)
      })
    },
    getVpcNetworkOffering () {
      return new Promise((resolve, reject) => {
        getAPI('listVPCOfferings', {
          id: this.resource.vpcofferingid
        }).then(json => {
          const vpcOffering = json?.listvpcofferingsresponse?.vpcoffering[0]
          resolve(vpcOffering)
          this.isOfferingNatMode = vpcOffering?.networkmode === 'NATTED' || false
          this.isOfferingRoutedMode = vpcOffering?.networkmode === 'ROUTED' || false
        }).catch(e => {
          reject(e)
        })
      })
    },
    publicLBNetworkExists () {
      getAPI('listNetworks', {
        vpcid: this.resource.id,
        supportedservices: 'LB'
      }).then(async json => {
        var lbNetworks = json.listnetworksresponse.network || []
        if (lbNetworks.length > 0) {
          this.publicLBExists = false
          for (var idx = 0; idx < lbNetworks.length; idx++) {
            const lbNetworkOffering = await this.getNetworkOffering(lbNetworks[idx].networkofferingid)
            const index = lbNetworkOffering.service.map(svc => { return svc.name }).indexOf('Lb')
            if (index !== -1 &&
              this.lbProviderMap.publicLb.vpc.indexOf(lbNetworkOffering.service.map(svc => { return svc.provider[0].name })[index]) !== -1) {
              this.publicLBExists = true
              break
            }
          }
        }
      })
    },
    fetchNetworkOfferings () {
      this.fetchLoading = true
      this.modalLoading = true
      const params = {
        forvpc: true,
        guestiptype: 'Isolated',
        state: 'Enabled'
      }
      if ((!this.isNsxEnabled || !['netris', 'nsx'].includes(this.zoneExtNetProvider.toLowerCase())) && !this.isOfferingRoutedMode) {
        params.supportedServices = 'SourceNat'
      }
      getAPI('listNetworkOfferings', params).then(json => {
        this.networkOfferings = json.listnetworkofferingsresponse.networkoffering || []
        var filteredOfferings = []
        const vpcLbServiceIndex = this.resource.service.map(svc => { return svc.name }).indexOf('Lb')
        for (var index in this.networkOfferings) {
          const offering = this.networkOfferings[index]
          const idx = offering.service.map(svc => { return svc.name }).indexOf('Lb')
          if (this.publicLBExists && (idx === -1 || this.lbProviderMap.publicLb.vpc.indexOf(offering.service.map(svc => { return svc.provider[0].name })[idx]) === -1)) {
            filteredOfferings.push(offering)
          } else if (!this.publicLBExists && vpcLbServiceIndex > -1) {
            const vpcLbServiceProviders = vpcLbServiceIndex === -1 ? undefined : this.resource.service[vpcLbServiceIndex].provider.map(provider => provider.name)
            const offeringLbServiceProvider = idx === -1 ? undefined : offering.service[idx].provider[0].name
            if (vpcLbServiceProviders && (!offeringLbServiceProvider || (offeringLbServiceProvider && vpcLbServiceProviders.includes(offeringLbServiceProvider)))) {
              filteredOfferings.push(offering)
            }
          } else {
            filteredOfferings.push(offering)
          }
        }
        this.networkOfferings = filteredOfferings
        if (this.isNsxEnabled || (this.zoneExtNetProvider && ['netris', 'nsx'].includes(this.zoneExtNetProvider.toLowerCase()))) {
          this.networkOfferings = this.networkOfferings.filter(offering => offering.networkmode === (this.isOfferingNatMode ? 'NATTED' : 'ROUTED'))
        }
        if (this.resource.asnumberid) {
          this.networkOfferings = this.networkOfferings.filter(offering => offering.routingmode === 'Dynamic')
        }
        this.fetchZoneASNumbers()
        this.form.networkOffering = this.networkOfferings[0].id
      }).catch(error => {
        this.$notifyError(error)
      }).finally(() => {
        this.fetchLoading = false
        this.modalLoading = false
      })
    },
    fetchLoadBalancers (id) {
      this.fetchLoading = true
      getAPI('listLoadBalancers', {
        networkid: id,
        page: this.page,
        pagesize: this.pageSize,
        listAll: true
      }).then(json => {
        this.internalLB[id] = json.listloadbalancersresponse.loadbalancer || []
        this.itemCounts.internalLB[id] = json.listloadbalancersresponse.count || 0
      }).finally(() => {
        this.fetchLoading = false
      })
    },
    fetchVMs (id) {
      this.fetchLoading = true
      getAPI('listVirtualMachines', {
        listAll: true,
        vpcid: this.resource.id,
        networkid: id,
        page: this.page,
        pagesize: this.pageSize
      }).then(json => {
        this.vms[id] = json.listvirtualmachinesresponse.virtualmachine || []
        this.itemCounts.vms[id] = json.listvirtualmachinesresponse.count || 0
      }).finally(() => {
        this.fetchLoading = false
      })
    },
    handleNetworkOfferingChange (networkOfferingId) {
      this.selectedNetworkOffering = this.networkOfferings.filter(offering => offering.id === networkOfferingId)[0]
    },
    handleNetworkAclChange (aclId) {
      if (aclId) {
        this.selectedNetworkAcl = this.networkAclList.filter(acl => acl.id === aclId)[0]
      } else {
        this.selectedNetworkAcl = {}
      }
    },
    closeModal () {
      this.$emit('close-action')
    },
    handleOpenModal () {
      this.initForm()
      this.fetchNetworkAclList()
      this.fetchNetworkOfferings()
      const cidr = this.resource.cidr
      const netmask = getNetmaskFromCidr(cidr)
      if (netmask) {
        this.gatewayPlaceholder = this.$t('label.create.tier.gateway.description', { value: cidr })
        this.netmaskPlaceholder = this.$t('label.create.tier.netmask.description', { value: netmask })
      }

      this.showCreateNetworkModal = true
      this.rules = {
        name: [{ required: true, message: this.$t('label.required') }],
        networkOffering: [{ required: true, message: this.$t('label.required') }],
        gateway: [{ required: true, message: this.$t('label.required') }],
        netmask: [{ required: true, message: this.$t('label.required') }],
        acl: [{ required: true, message: this.$t('label.required') }],
        vlan: [{ required: true, message: this.$t('message.please.enter.value') }]
      }
    },
    handleAddInternalLB (id) {
      this.initForm()
      this.showAddInternalLB = true
      this.networkid = id
      this.form.algorithm = 'Source'
      this.rules = {
        name: [{ required: true, message: this.$t('message.error.internallb.name') }],
        sourcePort: [{ required: true, message: this.$t('message.error.internallb.source.port') }],
        instancePort: [{ required: true, message: this.$t('message.error.internallb.instance.port') }],
        algorithm: [{ required: true, message: this.$t('label.required') }]
      }
    },
    handleAddNetworkSubmit () {
      if (this.modalLoading) return
      this.fetchLoading = true
      this.modalLoading = true

      this.formRef.value.validate().then(() => {
        const formRaw = toRaw(this.form)
        const values = this.handleRemoveFields(formRaw)

        this.showCreateNetworkModal = false
        var params = {
          vpcid: this.resource.id,
          domainid: this.resource.domainid,
          account: this.resource.account,
          networkOfferingId: values.networkOffering,
          name: values.name,
          displayText: values.name,
          gateway: values.gateway,
          netmask: values.netmask,
          zoneId: this.resource.zoneid,
          externalid: values.externalId,
          aclid: values.acl
        }

        if (values.vlan) {
          params.vlan = values.vlan
        }

        if (values.privatemtu) {
          params.privatemtu = values.privatemtu
        }

        if (values.asnumber && this.isASNumberRequired()) {
          params.asnumber = values.asnumber
        }

        postAPI('createNetwork', params).then(() => {
          this.$notification.success({
            message: this.$t('message.success.add.vpc.network')
          })
        }).catch(error => {
          this.$notifyError(error)
        }).finally(() => {
          this.parentFetchData()
          this.fetchData()
          this.fetchLoading = false
          this.modalLoading = false
        })
      }).catch((error) => {
        this.formRef.value.scrollToField(error.errorFields[0].name)
        this.fetchLoading = false
        this.modalLoading = false
      })
    },
    handleAddInternalLBSubmit () {
      if (this.modalLoading) return
      this.fetchLoading = true
      this.modalLoading = true
      this.formRef.value.validate().then(() => {
        const formRaw = toRaw(this.form)
        const values = this.handleRemoveFields(formRaw)

        postAPI('createLoadBalancer', {
          name: values.name,
          sourceipaddress: values.sourceIP,
          sourceport: values.sourcePort,
          instanceport: values.instancePort,
          algorithm: values.algorithm,
          networkid: this.networkid,
          sourceipaddressnetworkid: this.networkid,
          scheme: 'Internal'
        }).then(response => {
          this.$pollJob({
            jobId: response.createloadbalancerresponse.jobid,
            title: this.$t('message.create.internallb'),
            description: values.name,
            successMessage: this.$t('message.success.create.internallb'),
            successMethod: () => {
              this.fetchData()
              this.modalLoading = false
            },
            errorMessage: `${this.$t('message.create.internallb.failed')} ` + response,
            errorMethod: () => {
              this.fetchData()
              this.modalLoading = false
            },
            loadingMessage: this.$t('message.create.internallb.processing'),
            catchMessage: this.$t('error.fetching.async.job.result'),
            catchMethod: () => {
              this.fetchData()
              this.modalLoading = false
            }
          })
        }).catch(error => {
          console.error(error)
          this.$message.error(this.$t('message.create.internallb.failed'))
          this.modalLoading = false
        }).finally(() => {
          this.modalLoading = false
          this.fetchLoading = false
          this.showAddInternalLB = false
          this.fetchData()
        })
      }).catch((error) => {
        this.formRef.value.scrollToField(error.errorFields[0].name)
        this.fetchLoading = true
        this.modalLoading = false
      })
    },
    changePage (page, pageSize) {
      this.page = page
      this.pageSize = pageSize
      this.fetchData()
    },
    changePageSize (currentPage, pageSize) {
      this.page = currentPage
      this.pageSize = pageSize
      this.fetchData()
    }
  }
}
</script>

<style lang="scss" scoped>
.list {

  &__label {
    font-weight: bold;
  }

  &__col {
    flex: 1;

    @media (min-width: 480px) {
      &:not(:last-child) {
        margin-right: 20px;
      }
    }
  }

  &__item {
    margin-right: -8px;
    align-items: flex-start;

    &-outer-container {
      width: 100%;
    }

    &-container {
      display: flex;
      flex-direction: column;
      width: 100%;

      @media (min-width: 480px) {
        flex-direction: row;
        margin-bottom: 10px;
      }
    }
  }
}
</style>
